2011-03-29 21:27:00
有个需求,能否做到实现一个类似这样的函数:
1template <typename T1, typename T2>
2XXX Min(T1 t1, T2 t2)
3{
4 return (t1 < t2 ? t1 : t2);
5}
其中 XXX 是我们要推导出的类型。
以下是一个失败的尝试。
我记得 Loki 里有关于如何判断某个类型能否隐式转换为另一个类型的东西,大意如下:
1template <typename T, typename U>
2class Conversion
3{
4private:
5 typedef char Small;
6 class Big { char XXX[2]; };
7 static Small Test(U);
8 static Big Test(...);
9 static T MakeT();
10public:
11 enum
12 {
13 Exists = (sizeof(Test(MakeT())) == sizeof(Small)),
14 };
15};
如此,Conversion<T, U>::Exists 就能判断 T 到 U 的转换是否存在了。
然后再搞个选择:
1template <bool Condition, typename TypeIfTrue, typename TypeIfFalse>
2struct Select
3{
4 typedef TypeIfFalse Type;
5};
6
7template <typename TypeIfTrue, typename TypeIfFalse>
8struct Select<true, TypeIfTrue, TypeIfFalse>
9{
10 typedef TypeIfTrue Type;
11};
最后,再来个:
1struct NullType;
2
3template <typename T, typename U>
4struct CommonType
5{
6 typedef typename Select<Conversion<T, U>::exists,
7 U,
8 typename Select<Conversion<U, T>::exists,
9 T,
10 NullType>::Type
11 >::Type Type;
12};
那么 CommonType<T1, T2> 就是 T1 和 T2 之间哪个是他们的共有类型了。
测试:
1int main()
2{
3 CommonType<int, double>::Type m = 0;
4
5 return 0;
6}
调试,确认 m 是 double 的。但是反过来写 CommonType<double, int>::Type m = 0;,m 却是 int 的。
这说明这套机制一开始就有问题,Test(U) 和 Test(…) 两个重载函数中,Test(…) 不会在需要 double 转 int 时胜出。这是第一个问题。
第二个问题,当写下如下代码的时候:
1template <typename T1, typename T2>
2CommonType<T1, T2>::Type Min(T1 t1, T2 t2)
3{
4 return (t1 < t2 ? t1 : t2);
5}
编译无法通过。原因是返回类型中的 CommonType 中的模板参数 T、U 无法接受此时还不能确定的 T1、T2。
(更正:不是这个原因,返回类型前加 typename 即可。现在问题还是第一个问题。)
请教各位,有没有什么方法做到?欢迎指教~
C++ 0x 中就能很方便做到了:
1template <typename T1, typename T2>
2auto Min(T1 t1, T2 t2) -> decltype(t1 + t2)
3{
4 return (t1 < t2 ? t1 : t2);
5}
6
7int main()
8{
9 int a = 2;
10 double b = 1.0;
11 auto m = Min(a, b);
12
13 return 0;
14}
-- 首发:http://www.cppblog.com/Streamlet/archive/2011/03/29/142974.html